package uk.ac.tees.aetoolkit;

import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
import org.json.JSONObject;

import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.speech.RecognizerIntent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

/**
 * Weather class - used in the alarm clock application in the AEToolkit.
 * 
 * @author Sohail Rahman, Mark Williamson, Robert Sheffield
 * 
 */
public class Weather extends Activity {
	/**
	 * Textview variables to display weather information.
	 */
	private TextView textView = null;
	private TextView textView2 = null;
	private TextView textView3 = null;
	private TextView textView4 = null;
	/**
	 * Imageview variable to show appropriate image.
	 */
	private ImageView imageview = null;
	/**
	 * Variable used to show current location
	 */
	private String addressStr = "";
	/**
	 * String variable used to store spoken words from the user.
	 */
	private String speach = "";
	/**
	 * Variable to set the context to this class.
	 */
	Context ctx = this;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.layout_weather);
		//sets text view to appropriate layout text view.
		textView = (TextView) findViewById(R.id.textView1);
		TextView welcome = (TextView) findViewById(R.id.textView2);
		textView2 = (TextView) findViewById(R.id.textView3);
		textView3 = (TextView) findViewById(R.id.textView4);
		textView4 = (TextView) findViewById(R.id.textView5);
		imageview = (ImageView) findViewById(R.id.imageView1);
		//sets the select location button.
		Button selectL = (Button) findViewById(R.id.button3);
		//sets the help button.
		ImageButton weatherHelp = (ImageButton) findViewById(R.id.imageButton1);
		//on click listener for help which creates an alert dialog.
		weatherHelp.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				AlertDialog alertDialog;
				AlertDialog.Builder alertDialog2 = new AlertDialog.Builder(
						Weather.this);
				alertDialog2.setTitle("Help");
				alertDialog2
						.setMessage("Touchscreen use\n\nTo select your location click on select location, and select your location to see the weather.\n\nVoice Recognition use\n\n To pick your location, press the voice button and say your postcode." );
				alertDialog2.show();
			}
		});
		//gets an instance of calendar.
		Calendar calendar = Calendar.getInstance();
		//if the hour is past 12 tells user good afternoon (otherwise stays as good morning).
		if (calendar.get(Calendar.HOUR_OF_DAY) >= 12) {
			welcome.setText("Good Afternoon!");
		}
		//gets the current location using getCurrentlocation method.
		String location = getCurrentlocation();
		//gets the weather using getWeather method.
		getWeather(location);
		//on click listenener is set on the select location button.
		selectL.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				//creates a alert dialog prompting user to select a location.
				AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
				builder.setTitle("Please chose location");
				final CharSequence[] locations = { "Your current location",
						"London", "Birmingham", "Leeds", "Manchester",
						"Bristol" };
				builder.setItems(locations,
						new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface dialog, int item) {
								//depending on location pick the getWeather method is called with appropriate postcode and the address is updated on screen.
								if (item == 0) {
									getWeather(getCurrentlocation());
								} else if (item == 1) {
									getWeather("WC2E");
									addressStr = "London";
								} else if (item == 2) {
									getWeather("B1");
									addressStr = "Birmingham";
								} else if (item == 3) {
									getWeather("LS1");
									addressStr = "Leeds";
								} else if (item == 4) {
									getWeather("M1");
									addressStr = "Manchester";
								} else if (item == 5) {
									getWeather("BS1");
									addressStr = "Bristol";
								}

							}
						});
				//shows alert dialog.
				builder.show();

			}
		});
		//sets speak button for voice control.
		ImageButton speak = (ImageButton) findViewById(R.id.btnSpeak);
		//sets a on click listener to the button.
		speak.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				//creates intent for speech synthesis.
				Intent i = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
				i.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, "en-UK");
				// Start speech synthesis if phone supports it.
				try {
					//starts the intent.
					startActivityForResult(i, 1);
					//sets speacg to nothing.
					speach = "";
					//catch for if phone doesnt support speech to text.
				} catch (ActivityNotFoundException a) {
					Toast.makeText(getApplicationContext(),
							"Device doesnt support speech to text",
							Toast.LENGTH_SHORT).show();
				}
			}
		});
	}

	/**
	 * method to get the users current location.
	 * @return returns the latitude and longitude.
	 */
	public String getCurrentlocation() {
		// Location manager used to get longitude/latitude based on phones
		// location.
		LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		// gets the phones last known location.
		Location loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
		// formats the results in order to use in the JSON query.
		DecimalFormat df = new DecimalFormat("#.##");
		String longitude = "0.10";
		String latitude = "51.51";
		if (loc != null) {
			longitude = df.format(loc.getLongitude());
			latitude = df.format(loc.getLatitude());
		}
		// Gets the users location
		Geocoder myLocation = new Geocoder(this, Locale.getDefault());
		List<Address> myList = null;
		try {
			myList = myLocation.getFromLocation(Double.parseDouble(latitude),
					Double.parseDouble(longitude), 1);
		Address address = (Address) myList.get(0);	
			// Stores the different address lines
		addressStr = "";
		addressStr += address.getAddressLine(1) + ", ";
		addressStr += address.getAddressLine(2);
		} catch (NumberFormatException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return latitude + "," + longitude;
	}

	/**
	 * method to get the weather with the use of a JSON parser.
	 * @param loc used in the url of the JSON query.
	 */
	public void getWeather(String loc) {
		// Builds the url for the JSON query.
		String url = "http://www.myweather2.com/developer/forecast.ashx?uac=nZB70Wc1c2&output=json&query="
				+ loc + "&temp_unit=c";
		// Starts the AsyncTask.
		JSONParserDownload JDown = new JSONParserDownload();
		JDown.execute(url);
	}

	/**
	 * method to download the JSON string object asyncronsly.
	 *
	 */
	private class JSONParserDownload extends AsyncTask<String, String, String> {
		//variables to store the description of the weather.
		private String temp = "";
		private String humidity = "";
		private String description = "";
		private String code = "";

		@Override
		protected String doInBackground(String... uri) {
			try {
				// Creates a JSONParser object.
				JSONParser jParser = new JSONParser();
				// gets the JSON object from the url.

				JSONObject json = jParser.getJSONFromUrl(uri[0]);
				// Gets the current weather from the JSON object.
				JSONObject currentWeather = (JSONObject) json
						.getJSONObject("weather")
						.getJSONArray("curren_weather").get(0);
				// Sets the temperature from the JSON object
				temp = (String) currentWeather.get("temp");
				// Sets the humidity from the JSON object
				humidity = (String) currentWeather.get("humidity");
				// Sets the description from the JSON object
				description = (String) currentWeather.get("weather_text");
				// Sets the weather code from the JSON object
				code = (String) currentWeather.get("weather_code");
			} catch (Exception e) {
				temp = "Error Getting Weather Update";
				humidity = "Error Getting Weather Update";
				description = "Error Getting Weather Update";
				e.printStackTrace();
			}
			return temp;
		}

		@Override
		protected void onPostExecute(String result) {
			super.onPostExecute(result);
			// Displays result to user.
			textView.setText("The temperature is: " + temp + "°C");
			textView2.setText("The humidity is: " + humidity + "%");
			textView3.setText("todays description is: " + description);
			textView4.setText("Here is the weather at " + addressStr);
			//if statements to set image to display to user.
			if (code != "") {
				if (code.equals("0")) {
					imageview.setImageResource(R.drawable.sunny);
				} else if (code.equals("1") || code.equals("2")
						|| code.equals("3")) {
					imageview.setImageResource(R.drawable.cloudy);
				} else if (code.equals("10") || code.equals("45")
						|| code.equals("49") || code.equals("68")
						|| code.equals("69")) {
					imageview.setImageResource(R.drawable.fog);
				} else if (code.equals("21") || code.equals("29")
						|| code.equals("50") || code.equals("51")
						|| code.equals("56") || code.equals("57")
						|| code.equals("60") || code.equals("61")
						|| code.equals("62") || code.equals("63")
						|| code.equals("64") || code.equals("65")
						|| code.equals("66") || code.equals("67")
						|| code.equals("80") || code.equals("81")
						|| code.equals("82") || code.equals("83")
						|| code.equals("84") || code.equals("91")
						|| code.equals("92")) {
					imageview.setImageResource(R.drawable.rain);
				} else if (code.equals("22") || code.equals("23")
						|| code.equals("24") || code.equals("38")
						|| code.equals("39") || code.equals("70")
						|| code.equals("71") || code.equals("72")
						|| code.equals("73") || code.equals("74")
						|| code.equals("75") || code.equals("79")
						|| code.equals("85") || code.equals("86")
						|| code.equals("87") || code.equals("88")
						|| code.equals("93") || code.equals("94")) {
					imageview.setImageResource(R.drawable.snow);
				}
			} else {
				//default image.
				imageview.setImageResource(R.drawable.sunny);
			}
		}
	}

	/**
	 * Called when speech synthesis is started, used to determine what the user
	 * has said and add a relevant alarm accordingly.
	 */
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		// Flag to check if hour and minute has been set.
		if (resultCode == RESULT_OK && null != data) {
			// Creating an ArrayList to store speech data.
			ArrayList<String> text = data
					.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
			// Setting speech variable to what the user has spoken.
			speach = text.get(0);
			//deletes all spaces.
			speach = speach.replaceAll("\\s", "");
			Toast.makeText(ctx, speach, Toast.LENGTH_SHORT).show();
			//gets the weather from the users spoken location.
			getWeather(speach);
			//updates the address.
			addressStr = speach;
		}
	}
}
